home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / trace / tcpdump-2.2.1 / savefile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-26  |  7.3 KB  |  304 lines

  1. /*
  2.  * Copyright (c) 1990,1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static char rcsid[] =
  23.     "@(#)$Header: savefile.c,v 1.27 92/01/26 21:29:26 mccanne Exp $ (LBL)";
  24. #endif
  25.  
  26. /*
  27.  * savefile.c - supports offline use of tcpdump
  28.  *    Extraction/creation by Jeffrey Mogul, DECWRL
  29.  *    Modified by Steve McCanne, LBL.
  30.  *
  31.  * Used to save the received packet headers, after filtering, to
  32.  * a file, and then read them later.
  33.  * The first record in the file contains saved values for the machine
  34.  * dependent values so we can print the dump file on any architecture.
  35.  */
  36.  
  37. #include <stdio.h>
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40. #include <net/bpf.h>
  41.  
  42. #include "version.h"
  43. #include "savefile.h"
  44.  
  45. #define TCPDUMP_MAGIC 0xa1b2c3d4
  46.  
  47. /*
  48.  * The first record in the file contains saved values for some
  49.  * of the flags used in the printout phases of tcpdump.
  50.  * Many fields here are longs so compilers won't insert unwanted
  51.  * padding; these files need to be interchangeable across architectures.
  52.  */
  53. struct file_header {
  54.     u_long magic;
  55.     u_short version_major;
  56.     u_short version_minor;
  57.     long thiszone;        /* gmt to local correction */
  58.     u_long sigfigs;        /* accuracy of timestamps */
  59.     u_long snaplen;        /* max length saved portion of each pkt */
  60.     u_long linktype;
  61. };
  62.  
  63. int sf_swapped;
  64.  
  65. FILE *sf_readfile;
  66. FILE *sf_writefile;
  67.  
  68. static int
  69. sf_write_header(fp, linktype, thiszone, snaplen, precision)
  70.     FILE *fp;
  71.     int linktype;
  72.     int thiszone;
  73.     int snaplen;
  74.     int precision;
  75. {
  76.     struct file_header hdr;
  77.  
  78.     hdr.magic = TCPDUMP_MAGIC;
  79.     hdr.version_major = VERSION_MAJOR;
  80.     hdr.version_minor = VERSION_MINOR;
  81.  
  82.     hdr.thiszone = thiszone;
  83.     hdr.snaplen = snaplen;
  84.     hdr.sigfigs = precision;
  85.     hdr.linktype = linktype;
  86.  
  87.     if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
  88.         return -1;
  89.  
  90.     return 0;
  91. }
  92.  
  93. static void
  94. swap_hdr(hp)
  95.     struct file_header *hp;
  96. {
  97.     hp->version_major = SWAPSHORT(hp->version_major);
  98.     hp->version_minor = SWAPSHORT(hp->version_minor);
  99.     hp->thiszone = SWAPLONG(hp->thiszone);
  100.     hp->sigfigs = SWAPLONG(hp->sigfigs);
  101.     hp->snaplen = SWAPLONG(hp->snaplen);
  102.     hp->linktype = SWAPLONG(hp->linktype);
  103. }
  104.  
  105. int
  106. sf_read_init(fname, linktypep, thiszonep, snaplenp, precision)
  107.     char *fname;
  108.     int *linktypep, *thiszonep, *snaplenp, *precision;
  109. {
  110.     register FILE *fp;
  111.     struct file_header hdr;
  112.  
  113.     if (fname[0] == '-' && fname[1] == '\0')
  114.         fp = stdin;
  115.     else {
  116.         fp = fopen(fname, "r");
  117.         if (fp == 0) {
  118.             (void) fprintf(stderr, "tcpdump: fopen: ");
  119.             perror(fname);
  120.             exit(1);
  121.         }
  122.     }
  123.     if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
  124.         (void) fprintf(stderr, "tcpdump: fread: ");
  125.         perror(fname);
  126.         exit(1);
  127.     }
  128.     if (hdr.magic != TCPDUMP_MAGIC) {
  129.         if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC)
  130.             return SFERR_BADF;
  131.         sf_swapped = 1;
  132.         swap_hdr(&hdr);
  133.     }
  134.     if (hdr.version_major < VERSION_MAJOR)
  135.         return SFERR_BADVERSION;
  136.  
  137.     *thiszonep = hdr.thiszone;
  138.     *snaplenp = hdr.snaplen;
  139.     *linktypep = hdr.linktype;
  140.     *precision = hdr.sigfigs;
  141.  
  142.     sf_readfile = fp;
  143.  
  144.     return 0;
  145. }
  146.  
  147. /*
  148.  * Print out packets stored in the file initilized by sf_read_init().
  149.  * If cnt >= 0, return after 'cnt' packets, otherwise continue until eof.
  150.  */
  151. int
  152. sf_read(filtp, cnt, snaplen, printit)
  153.     struct bpf_program *filtp;
  154.     int cnt, snaplen;
  155.     void (*printit)();
  156. {
  157.     struct packet_header h;
  158.     u_char *buf;
  159.     struct bpf_insn *fcode = filtp->bf_insns;
  160.     int status = 0;
  161.  
  162.     buf = (u_char *)malloc(snaplen);
  163.  
  164.     while (status == 0) {
  165.         status = sf_next_packet(&h, buf, snaplen);
  166.  
  167.         if (status)
  168.             break;
  169.         /*
  170.          * XXX It's possible (and likely) for us to screw up the
  171.          * network layer alignment when we pass down packets from 
  172.          * this point (ip_print deals by copying the ip header
  173.          * to an aligned buffer).  There doesn't seem to be a 
  174.          * clean way to fix this.  We could compute an offset 
  175.          * from the link type (which would have to be passed in),
  176.          * but that only works for fixed size headers.
  177.          */
  178.         if (bpf_filter(fcode, buf, h.len, h.caplen)) {
  179.             if (cnt >= 0 && --cnt < 0)
  180.                 break;
  181.             (*printit)(buf, &h.ts, h.len, h.caplen);
  182.         }
  183.     }
  184.  
  185.     if (status == SFERR_EOF)
  186.         /* treat EOF's as okay status */
  187.         status = 0;
  188.  
  189.     free((char *)buf);
  190.     return status;
  191. }
  192.  
  193. /*
  194.  * Read sf_readfile and return the next packet.  Return the header in hdr 
  195.  * and the contents in buf.  Return 0 on success, SFERR_EOF if there were 
  196.  * no more packets, and SFERR_TRUNC if a partial packet was encountered.
  197.  */
  198. int
  199. sf_next_packet(hdr, buf, buflen)
  200.     struct packet_header *hdr;
  201.     u_char *buf;
  202.     int buflen;
  203. {
  204.     FILE *fp = sf_readfile;
  205.  
  206.     /* read the stamp */
  207.     if (fread((char *)hdr, sizeof(struct packet_header), 1, fp) != 1) {
  208.         /* probably an EOF, though could be a truncated packet */
  209.         return SFERR_EOF;
  210.     }
  211.  
  212.     if (sf_swapped) {
  213.         /* these were written in opposite byte order */
  214.         hdr->caplen = SWAPLONG(hdr->caplen);
  215.         hdr->len = SWAPLONG(hdr->len);
  216.         hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
  217.         hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
  218.     }
  219.  
  220.     if (hdr->caplen > buflen)
  221.         return SFERR_BADF;
  222.  
  223.     /* read the packet itself */
  224.  
  225.     if (fread((char *)buf, hdr->caplen, 1, fp) != 1)
  226.         return SFERR_TRUNC;
  227.  
  228.     return 0;
  229. }
  230.  
  231. /*
  232.  * Initialize so that sf_write() will output to the file named 'fname'.
  233.  */
  234. void
  235. sf_write_init(fname, linktype, thiszone, snaplen, precision)
  236.     char *fname;
  237.     int linktype;
  238.     int thiszone;
  239.     int snaplen;
  240.     int precision;
  241. {
  242.     if (fname[0] == '-' && fname[1] == '\0')
  243.         sf_writefile = stdout;
  244.     else {
  245.         sf_writefile = fopen(fname, "w");
  246.         if (sf_writefile == 0) {
  247.             (void) fprintf(stderr, "tcpdump: fopen: ");
  248.             perror(fname);
  249.             exit(1);
  250.         }
  251.     }
  252.     (void)sf_write_header(sf_writefile,
  253.         linktype, thiszone, snaplen, precision);
  254. }
  255.  
  256. /*
  257.  * Output a packet to the intialized dump file.
  258.  */
  259. void
  260. sf_write(sp, tvp, length, caplen)
  261.     u_char *sp;
  262.     struct timeval *tvp;
  263.     int length;
  264.     int caplen;
  265. {
  266.     struct packet_header h;
  267.  
  268.     h.ts.tv_sec = tvp->tv_sec;
  269.     h.ts.tv_usec = tvp->tv_usec;
  270.     h.len = length;
  271.     h.caplen = caplen;
  272.  
  273.     (void)fwrite((char *)&h, sizeof h, 1, sf_writefile);
  274.     (void)fwrite((char *)sp, caplen, 1, sf_writefile);
  275. }
  276.  
  277. void
  278. sf_err(code)
  279.     int code;
  280. {
  281.     switch (code) {
  282.     case SFERR_BADVERSION:
  283.         error("archaic file format");
  284.         /* NOTREACHED */
  285.  
  286.     case SFERR_BADF:
  287.         error("bad dump file format");
  288.         /* NOTREACHED */
  289.  
  290.     case SFERR_TRUNC:
  291.         error("truncated dump file");
  292.         /* NOTREACHED */
  293.  
  294.     case SFERR_EOF:
  295.         error("EOF reading dump file");
  296.         /* NOTREACHED */
  297.  
  298.     default:
  299.         error("unknown dump file error code in sf_err()");
  300.         /* NOTREACHED */
  301.     }
  302.     abort();
  303. }
  304.